 package org.zfes.snowier.zbss.xzy.face;
 import java.util.List;

import org.zfes.snowier.zbss.xzy.face.enums.ErrorInfo;
import org.zfes.snowier.zbss.xzy.face.enums.ImageFormat;
public class FaceEngine{
	 
   static {
     String os = System.getProperty("os.name");
     if (os.toLowerCase().startsWith("win")) {
       System.loadLibrary("libarcsoft_face_engine_jni");
     } else {
       System.loadLibrary("arcsoft_face_engine_jni");
     } 
   }
   
   private final int ASF_FACE_DETECT = 1;
   private final int ASF_FACE_RECOGNITION = 4;
   private final int ASF_AGE = 8;
   private final int ASF_GENDER = 16;
   private final int ASF_FACE3DANGLE = 32;
   public static final int ASF_LIVENESS = 128;
   private long handle = 0L;
   int code = -1;
   
   private FaceInfo[] faceInfoArray;
   private AgeInfo[] ageInfoArray;
   private GenderInfo[] genderInfoArray;
   private Face3DAngle[] faceAngleArray;
   private LivenessInfo[] livenessInfoArray;
   
   public void active(String appId, String sdkKey) {
     if (appId == null || sdkKey == null) {
       throw new IllegalArgumentException("appId or sdkKey is empty");
     }
     int resultCode = activeFaceEngine(appId, sdkKey);
     if (!ErrorInfo.MOK.getValue().equals(Integer.valueOf(resultCode)) && !ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue().equals(Integer.valueOf(resultCode))) {
       throw new IllegalArgumentException(ErrorInfo.getValidEnum(Integer.valueOf(resultCode)).name());
     }
   }
   public void init(EngineConfiguration engineConfiguration) {
     long detectMode = engineConfiguration.getDetectMode().getValue();
     int detectFaceOrientPriority = engineConfiguration.getDetectFaceOrientPriority().getValue();
     int detectFaceScaleVal = engineConfiguration.getDetectFaceScaleVal().intValue();
     int detectFaceMaxNum = engineConfiguration.getDetectFaceMaxNum().intValue();
     int combinedMask = 0;
     if (engineConfiguration.getFunctionConfiguration().isSupportFaceDetect().booleanValue()) {
       combinedMask |= 0x1;
     }
     if (engineConfiguration.getFunctionConfiguration().isSupportFaceRecognition().booleanValue()) {
       combinedMask |= 0x4;
     }
     if (engineConfiguration.getFunctionConfiguration().isSupportAge().booleanValue()) {
       combinedMask |= 0x8;
     }
     if (engineConfiguration.getFunctionConfiguration().isSupportGender().booleanValue()) {
       combinedMask |= 0x10;
     }
     if (engineConfiguration.getFunctionConfiguration().isSupportFace3dAngle().booleanValue()) {
       combinedMask |= 0x20;
     }
     if (engineConfiguration.getFunctionConfiguration().isSupportLiveness().booleanValue()) {
       combinedMask |= 0x80;
     }
     this.handle = initFaceEngine(detectMode, detectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, this);
     if (!ErrorInfo.MOK.getValue().equals(Integer.valueOf(this.code))) {
       throw new IllegalArgumentException("init fail:" + ErrorInfo.getValidEnum(Integer.valueOf(this.code)).name());
     }
     if ((combinedMask & 0x1) != 0) {
       this.faceInfoArray = new FaceInfo[detectFaceMaxNum];
       
       for (int i = 0; i < detectFaceMaxNum; i++) {
         this.faceInfoArray[i] = new FaceInfo();
       }
     } 
     
     if ((combinedMask & 0x8) != 0) {
       this.ageInfoArray = new AgeInfo[detectFaceMaxNum];
       
       for (int i = 0; i < detectFaceMaxNum; i++) {
         this.ageInfoArray[i] = new AgeInfo();
       }
     } 
     
     if ((combinedMask & 0x10) != 0) {
       this.genderInfoArray = new GenderInfo[detectFaceMaxNum];
       
       for (int i = 0; i < detectFaceMaxNum; i++) {
         this.genderInfoArray[i] = new GenderInfo();
       }
     } 
     
     if ((combinedMask & 0x20) != 0) {
       this.faceAngleArray = new Face3DAngle[detectFaceMaxNum];
       
       for (int i = 0; i < detectFaceMaxNum; i++) {
         this.faceAngleArray[i] = new Face3DAngle();
       }
     } 
     if ((combinedMask & 0x80) != 0) {
       this.livenessInfoArray = new LivenessInfo[detectFaceMaxNum];
       for (int i = 0; i < detectFaceMaxNum; i++) {
         this.livenessInfoArray[i] = new LivenessInfo();
       }
     } 
   }
   public int unInit() {
     if (this.handle != 0L) {
       int unInitEngineCode = unInitFaceEngine(this.handle);
       this.handle = 0L;
       return unInitEngineCode;
     } 
     return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
   }
   
   public int detectFaces(byte[] data, int width, int height, ImageFormat imageFormat, List<FaceInfo> faceInfoList) {
     if (width <= 0 || height <= 0) {
       return ErrorInfo.MERR_ASF_IMAGE_WIDTH_HEIGHT_NOT_SUPPORT.getValue().intValue();
     }
     if (faceInfoList == null || data == null || imageFormat == null)
     {
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue();
     }
     
     switch (imageFormat) {
       case CP_PAF_NV21:
       case CP_PAF_NV12:
       case CP_PAF_I420:
         if (data.length != width * height * 3 / 2) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
       case CP_PAF_BGR24:
         if (data.length != width * height * 3) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
       case CP_PAF_YUYV:
         if (data.length != width * height * 2) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
     } 
     faceInfoList.clear();
     int count = detectFaces(this.handle, data, width, height, imageFormat.getValue(), this.faceInfoArray, this);
     
     if (count > 0) {
       for (int i = 0; i < count; i++) {
         faceInfoList.add(new FaceInfo(this.faceInfoArray[i]));
       }
     }
     return this.code;
   }
   public int process(byte[] data, int width, int height, ImageFormat imageFormat, List<FaceInfo> faceInfoList, FunctionConfiguration functionConfiguration) {
     if (width <= 0 || height <= 0) {
       return ErrorInfo.MERR_ASF_IMAGE_WIDTH_HEIGHT_NOT_SUPPORT.getValue().intValue();
     }
     if (faceInfoList == null || data == null || imageFormat == null)
     {
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue();
     }
     
     switch (imageFormat) {
       case CP_PAF_NV21:
       case CP_PAF_NV12:
       case CP_PAF_I420:
         if (data.length != width * height * 3 / 2) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
       case CP_PAF_BGR24:
         if (data.length != width * height * 3) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
       case CP_PAF_YUYV:
         if (data.length != width * height * 2) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
     } 
     
     int _combinedMask = 0;
     if (functionConfiguration.isSupportFaceDetect().booleanValue()) {
       _combinedMask |= 0x1;
     }
     if (functionConfiguration.isSupportFaceRecognition().booleanValue()) {
       _combinedMask |= 0x4;
     }
     if (functionConfiguration.isSupportAge().booleanValue()) {
       _combinedMask |= 0x8;
     }
     if (functionConfiguration.isSupportGender().booleanValue()) {
       _combinedMask |= 0x10;
     }
     if (functionConfiguration.isSupportFace3dAngle().booleanValue()) {
       _combinedMask |= 0x20;
     }
     if (functionConfiguration.isSupportLiveness().booleanValue()) {
       _combinedMask |= 0x80;
     }
 
     
     process(this.handle, data, width, height, imageFormat.getValue(), faceInfoList.<FaceInfo>toArray(new FaceInfo[0]), _combinedMask, this);
 
     
     return this.code;
   }
 
   public int extractFaceFeature(byte[] data, int width, int height, ImageFormat imageFormat, FaceInfo faceInfo, FaceFeature feature) {
     if (width <= 0 || height <= 0) {
       return ErrorInfo.MERR_ASF_IMAGE_WIDTH_HEIGHT_NOT_SUPPORT.getValue().intValue();
     }
     if (feature == null || imageFormat == null || feature
       .getFeatureData() == null || (feature
       .getFeatureData()).length < 1032 || faceInfo == null || data == null)
     {
       
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue();
     }
     switch (imageFormat) {
       case CP_PAF_NV21:
       case CP_PAF_NV12:
       case CP_PAF_I420:
         if (data.length != width * height * 3 / 2) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
       case CP_PAF_BGR24:
         if (data.length != width * height * 3) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
       case CP_PAF_YUYV:
         if (data.length != width * height * 2) {
           return ErrorInfo.MERR_ASF_EX_INVALID_IMAGE_INFO.getValue().intValue();
         }
         break;
     } 
     
     extractFaceFeature(this.handle, data, width, height, imageFormat.getValue(), faceInfo.getRect(), faceInfo.getOrient(), feature.getFeatureData(), this);
 
     
     return this.code;
   }
   public int compareFaceFeature(FaceFeature feature1, FaceFeature feature2, FaceSimilar faceSimilar) {
     if (feature1 == null || feature1.getFeatureData() == null || feature2 == null || feature2.getFeatureData() == null || faceSimilar == null)
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue(); 
     if (this.handle == 0L) {
       return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
     }
     
     faceSimilar.setScore(pairMatching(this.handle, feature1.getFeatureData(), feature2.getFeatureData(), this));
     
     return this.code;
   }
 
   public int getAge(List<AgeInfo> ageInfoList) {
     if (ageInfoList == null) {
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue();
     }
     if (this.handle == 0L) {
       return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
     }
     
     ageInfoList.clear();
     int count = getAge(this.handle, this.ageInfoArray, this);
     
     if (count > 0) {
       for (int i = 0; i < count; i++) {
         ageInfoList.add(new AgeInfo(this.ageInfoArray[i]));
       }
     }
     return this.code;
   }
   public int getGender(List<GenderInfo> genderInfoList) {
     if (genderInfoList == null) {
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue();
     }
     if (this.handle == 0L) {
       return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
     }
     
     genderInfoList.clear();
     
     int count = getGender(this.handle, this.genderInfoArray, this);
 
     
     if (count > 0) {
       for (int i = 0; i < count; i++) {
         genderInfoList.add(new GenderInfo(this.genderInfoArray[i]));
       }
     }
     return this.code;
   }
   public int getFace3DAngle(List<Face3DAngle> face3DAngleList) {
     if (face3DAngleList == null)
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue(); 
     if (this.handle == 0L) {
       return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
     }
     face3DAngleList.clear();
     
     int count = getFace3DAngle(this.handle, this.faceAngleArray, this);
     
     for (int i = 0; i < count; i++) {
       face3DAngleList.add(new Face3DAngle(this.faceAngleArray[i]));
     }
     return this.code;
   }
 
   
   public int getLiveness(List<LivenessInfo> livenessInfoList) {
     if (livenessInfoList == null) {
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue();
     }
     if (this.handle == 0L) {
       return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
     }
     
     livenessInfoList.clear();
     int count = getLiveness(this.handle, this.livenessInfoArray, this);
     for (int i = 0; i < count; i++) {
       livenessInfoList.add(new LivenessInfo(this.livenessInfoArray[i]));
     }
     return this.code;
   }
   public int getVersion(VersionInfo versionInfo) {
     if (versionInfo == null)
       return ErrorInfo.MERR_INVALID_PARAM.getValue().intValue(); 
     if (this.handle == 0L) {
       return ErrorInfo.MERR_BAD_STATE.getValue().intValue();
     }
     versionInfo.setVersion(getVersion(this.handle));
     return ErrorInfo.MOK.getValue().intValue();
   }
   
   private native long initFaceEngine(long detectMode, int detectFaceOrientPriority, int detectFaceScaleVal, int detectFaceMaxNum, int combinedMask, FaceEngine faceEngine);
   
   private native int activeFaceEngine(String appId, String sdkKey);
   
   private native int activeFaceEngine(String paramString1, String paramString2, String paramString3);
   
   private native int unInitFaceEngine(long handle);
   
   private native int detectFaces(long handle, byte[] data, int width, int paramInt2, int height, FaceInfo[] faceInfo, FaceEngine faceEngine);
   
   private native void process(long handle, byte[] data, int width, int height, int imageFormat, FaceInfo[] faceInfoArray, int _combinedMask, FaceEngine faceEngine);
   
   private native void extractFaceFeature(long handle, byte[] data, int width, int height, int imageFormat, Rect rect, int orient, byte[] featureData, FaceEngine faceEngine);
   
   private native float pairMatching(long handle, byte[] featureData1, byte[] featureData2, FaceEngine faceEngine);
   
   
   private native int getAge(long handle, AgeInfo[] ageInfoArray, FaceEngine faceEngine);
   
   private native int getGender(long handle, GenderInfo[] genderInfoArray, FaceEngine faceEngine);
   
   private native int getFace3DAngle(long handle, Face3DAngle[] face3DAngleArray, FaceEngine faceEngine);
   
   private native int getLiveness(long handle, LivenessInfo[] LivenessInfoArray, FaceEngine faceEngine);
   
   private native String getVersion(long handle);
 }

